package com.dmgis.hndz.common.utils;


import com.dmgis.entity.*;
import com.dmgis.hndz.sddz.service.Zdda01aService;
import com.dmgis.hndz.service.impl.CommonServiceImpl;
import com.dmgis.hndz.pojo.ColorAndNameDto;
import com.dmgis.hndz.pojo.Location;
import com.dmgis.hndz.pojo.MapPoint;
import com.dmgis.service.DmServiceConnector;
import com.dmgis.service.MapXML;
import com.dmgis.weblib.*;
import javafx.geometry.Point3D;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class DmgisUtils {
    @Autowired
    private Zdda01aService zdda01aService;

    /**
     * 判断点在多边形内
     *
     * @param mapPoint
     * @param scope
     * @return
     */
    public static boolean isScope(MapPoint mapPoint, List<List<Double>> scope) {

        List<DmMapPoint> dmMapPoints = new ArrayList<>();
        for (List<Double> point : scope) {
            dmMapPoints.add(new DmMapPoint(point.get(0), point.get(1)));
        }

        return MapCommon.pointWithinPolygon(dmMapPoints, mapPoint.getLon(), mapPoint.getLat());
    }

    public static List<DmsLayer> getService() {
        DmServiceConnector conn = new DmServiceConnector("192.168.0.23", "8808");//连接客户端
        try {
            String res = conn.getServiceXml("yl", 6, "");//访问客户端 接收返回的XML数据
            MapXML mapXML = new MapXML();
            DmMapServiceInfo dmMapServiceInfo = mapXML.dmGetProjServers(res);//解析XML为实体类
            System.out.println(res);
            List<DmsLayer> layers = dmMapServiceInfo.getLayers();
            return layers;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 兰伯特转经纬度
     *
     * @param lon
     * @param lat
     * @return
     */
    public static DmMapPoint lbtToWgs(Double lon, Double lat) {
        //当前投影
        MapProjPara paralbt = new MapProjPara();

        paralbt.setpProjType((short) 4);//兰伯特
        paralbt.setpEarthParam((short) 1);//椭球参数 北京54
        paralbt.setpLon(110);
        paralbt.setPlat(30);
        paralbt.setPlat1(30);
        paralbt.setPlat2(60);

        //目的投影
        MapProjPara paraWgs = new MapProjPara();
        paraWgs.setpProjType((short) 1);//投影类型，这里是地理坐标
        paraWgs.setpEarthParam((short) 7);//椭球参数,这里是WGS84
        //以下和其它参数 如果不设置会取默认值
        paraWgs.setpLon(0);//中央经线
        paraWgs.setPlat(0);//原点纬度
        paraWgs.setPlat1(0);//空间数据双纬线1
        paraWgs.setPlat2(0);//空间数据双纬线2

        MapProj mapProj = new MapProj(paralbt, paraWgs);

        boolean flag = mapProj.getM_biFlag();//投影参数初始化是否成功

        double[] res = mapProj.Convxy(lon, lat);//投影过后的点

        return new DmMapPoint(Double.parseDouble(String.format("%.6f", res[0])), Double.parseDouble(String.format("%.6f", res[1])));
    }

    /**
     * 地理坐标转兰伯特坐标
     *
     * @param lon
     * @param lat
     * @return
     */
    public static DmMapPoint wgsToLbt(Double lon, Double lat) {
        //当前投影
        MapProjPara paraold = new MapProjPara();
        paraold.setpProjType((short) 1);//投影类型，这里是地理坐标
        paraold.setpEarthParam((short) 7);//椭球参数,这里是WGS84
        //以下和其它参数 如果不设置会取默认值
        paraold.setpLon(0);//中央经线
        paraold.setPlat(0);//原点纬度
        paraold.setPlat1(0);//空间数据双纬线1
        paraold.setPlat2(0);//空间数据双纬线2

        //目的投影
        MapProjPara paranew = new MapProjPara();

        paranew.setpProjType((short) 4);//兰伯特
        paranew.setpEarthParam((short) 1);//椭球参数 北京54
        paranew.setpLon(110);
        paranew.setPlat(30);
        paranew.setPlat1(30);
        paranew.setPlat2(60);

        MapProj mapProj = new MapProj(paraold, paranew);

        boolean flag = mapProj.getM_biFlag();//投影参数初始化是否成功

        double[] res = mapProj.Convxy(lon, lat);//投影过后的点

        return new DmMapPoint(Double.parseDouble(String.format("%.2f", res[0])), Double.parseDouble(String.format("%.2f", res[1])));
    }

    /**
     * 计算面雨量(按照兰伯特坐标计算)
     *
     * @param min         最小z值
     * @param max         最大z值
     * @param fvals       符合条件的所有z值
     * @param dmMapPoints 点集(地图范围)
     * @param point3Ds    站点数据（坐标xy，雨量z）
     * @return
     */
    public static double getAreaRain(float min, float max, float[] fvals, List<DmMapPoint> dmMapPoints, List<Point3D> point3Ds) {
        // 获取外接矩形
        MapCommon mapCommon = new MapCommon();
        DmMapRectangle getobjrect = mapCommon.getObjRect(dmMapPoints);
        System.err.println(getobjrect);
        // 得到网格:通过经度获取列数，通过纬度获取行数
        int colSize = (int) (getobjrect.getMaxX() - getobjrect.getMinX()) / 1000;//列
        int rowSize = (int) (getobjrect.getMaxY() - getobjrect.getMinY()) / 1000;//行
        // 行列间距
        double xDistance = (getobjrect.getMaxX() - getobjrect.getMinX()) / colSize;//列间距
        double yDistance = (getobjrect.getMaxY() - getobjrect.getMinY()) / rowSize;//行间距
        // 生成三角网

        TinAnalysis tin = new TinAnalysis();
        tin.init();
        // 三角网插值
        for (Point3D point3D : point3Ds) {
            tin.addPoint(point3D.getX(), point3D.getY(), point3D.getZ());
        }
        //计算四个最近点的值
        tin.calculate4PintZValue(getobjrect);
        // 构建三角网
        tin.dmmesh();
        System.err.println("三角网完成");
        long start = System.currentTimeMillis() / 1000;
        // 设置grid分析
        GridAnalysis gridAnalysis = new GridAnalysis();
        DmGridInfo dmGridInfo = new DmGridInfo();
        dmGridInfo.setRows(rowSize);
        dmGridInfo.setCols(colSize);
        dmGridInfo.setxMin(getobjrect.getMinX());
        dmGridInfo.setxMax(getobjrect.getMaxX());
        dmGridInfo.setyMin(getobjrect.getMinY());
        dmGridInfo.setyMax(getobjrect.getMaxY());
        dmGridInfo.setzMin(min);
        dmGridInfo.setzMax(max);
        gridAnalysis.setInfo(dmGridInfo);
        gridAnalysis.setfValS(fvals);
        double x0 = 0, y0 = 0, z0 = 0;
        // 用于对比点在面内的坐标
        List<DmMapPoint> mapPoints = new ArrayList<>();
        // 用来获取雨量的坐标
        List<DmMapPoint> rainPoints = new ArrayList<>();
        for (int row = 0; row < dmGridInfo.getRows(); row++) {
            for (int col = 0; col < dmGridInfo.getCols(); col++) {
                x0 = getobjrect.getMinX() + col * xDistance;
                y0 = getobjrect.getMinY() + row * yDistance;
                z0 = tin.getPointValue(x0, y0);
                mapPoints.add(new DmMapPoint(x0, y0));
                rainPoints.add(new DmMapPoint(row, col));
                gridAnalysis.setValue(row, col, (float) z0);
            }
        }
        int count = 0;
        Float rainNum = 0.00f;
        System.err.println("dmMapPoints :" + dmMapPoints.size());
        dmMapPoints.remove(dmMapPoints.size() - 1);
        for (int i = 0; i < mapPoints.size(); i++) {
            double pointX = mapPoints.get(i).getX();
            double pointY = mapPoints.get(i).getY();
            boolean b = MapCommon.pointWithinPolygon(dmMapPoints, pointX, pointY);
            if (b) {
                int x = (int) rainPoints.get(i).getX();
                int y = (int) rainPoints.get(i).getY();
                float value = gridAnalysis.getValue(x, y);
                if (value == -99999.0) {
                    value = 0;
                }
                rainNum += value;
                count++;
            }
        }
        System.err.println("总雨量：" + rainNum);
        System.err.println("格点数：" + count);
        System.err.println("开始计算...");
        System.err.println("结果：" + rainNum / count);
        return rainNum / count;


    }

    /**
     * 计算面雨量(按照经纬度坐标计算)
     *
     * @param min         最小z值
     * @param max         最大z值
     * @param fvals       符合条件的所有z值
     * @param dmMapPoints 点集(地图范围)
     * @param point3Ds    站点数据（坐标xy，雨量z）
     * @return
     */
    public static double getAreaRainWgs(float min, float max, float[] fvals, List<DmMapPoint> dmMapPoints, List<Point3D> point3Ds) {
        System.err.println("fvalsLength:" + fvals.length);
        // 获取外接矩形
        MapCommon mapCommon = new MapCommon();
        DmMapRectangle getobjrect = mapCommon.getObjRect(dmMapPoints);
        System.err.println(getobjrect);
        // 得到网格:通过经度获取列数，通过纬度获取行数
        int colSize = (int) ((getobjrect.getMaxX() - getobjrect.getMinX()) / 0.01);//列
        int rowSize = (int) ((getobjrect.getMaxY() - getobjrect.getMinY()) / 0.01);//行
        // 行列间距
        double xDistance = (getobjrect.getMaxX() - getobjrect.getMinX()) / colSize;//列间距
        double yDistance = (getobjrect.getMaxY() - getobjrect.getMinY()) / rowSize;//行间距
        // 生成三角网

        TinAnalysis tin = new TinAnalysis();
        tin.init();
        // 三角网插值
        System.err.println("三角网插值");
        for (Point3D point3D : point3Ds) {
            System.out.println("x0:" + point3D.getX() + "\ty0:" + point3D.getY() + "\tz0:" + point3D.getZ());
            tin.addPoint(point3D.getX(), point3D.getY(), point3D.getZ());
        }
        //计算四个最近点的值
        tin.calculate4PintZValue(getobjrect);
        // 构建三角网
        tin.dmmesh();
        System.err.println("三角网完成");
        long start = System.currentTimeMillis() / 1000;
        // 设置grid分析
        GridAnalysis gridAnalysis = new GridAnalysis();
        DmGridInfo dmGridInfo = new DmGridInfo();
        dmGridInfo.setRows(rowSize);
        dmGridInfo.setCols(colSize);
        dmGridInfo.setxMin(getobjrect.getMinX());
        dmGridInfo.setxMax(getobjrect.getMaxX());
        dmGridInfo.setyMin(getobjrect.getMinY());
        dmGridInfo.setyMax(getobjrect.getMaxY());
        dmGridInfo.setzMin(min);
        dmGridInfo.setzMax(max);
        gridAnalysis.setInfo(dmGridInfo);
        gridAnalysis.setfValS(new float[rowSize * colSize]);
        double x0 = 0, y0 = 0, z0 = 0;
        // 用于对比点在面内的坐标
        List<DmMapPoint> mapPoints = new ArrayList<>();
        // 用来获取雨量的坐标
        List<DmMapPoint> rainPoints = new ArrayList<>();
//        System.out.println(tin.getPointValue(120.026595, 29.182172));
//        System.out.println("格点插值");
        for (int row = 0; row < dmGridInfo.getRows(); row++) {
            for (int col = 0; col < dmGridInfo.getCols(); col++) {
                x0 = getobjrect.getMinX() + col * xDistance;
                y0 = getobjrect.getMinY() + row * yDistance;
                z0 = tin.getPointValue(x0, y0);
                System.out.println("x0:" + x0 + "\ty0:" + y0 + "\tz0:" + z0);
                mapPoints.add(new DmMapPoint(x0, y0));
                rainPoints.add(new DmMapPoint(row, col));
                gridAnalysis.setValue(row, col, (float) z0);
//                System.out.println("row: " + row + "\tcol:" + col + "\tvalue:" + z0);
            }
        }
        float[] floats = gridAnalysis.getfValS();

        int count = 0;
        Float rainNum = 0.00f;
//        System.err.println("dmMapPoints :" + dmMapPoints.size());
//        System.out.println("计算面雨量");
        dmMapPoints.remove(dmMapPoints.size() - 1);
        for (int i = 0; i < mapPoints.size(); i++) {
            double pointX = mapPoints.get(i).getX();
            double pointY = mapPoints.get(i).getY();
            boolean b = MapCommon.pointWithinPolygon(dmMapPoints, pointX, pointY);
            System.out.println("x:" + pointX + "\ty:" + pointY + "\t是否在范围内:" + b);
            if (b) {
                int x = (int) rainPoints.get(i).getX();
                int y = (int) rainPoints.get(i).getY();
                float value = gridAnalysis.getValue(x, y);
                System.out.println("row:" + x + "\tcol:" + y + "\tvalue:" + value);
                if (value < 0) {
                    value = 0;
                }
                rainNum += value;
                count++;
            }
        }
        System.err.println("总雨量：" + rainNum);
        System.err.println("格点数：" + count);
        System.err.println("开始计算...");
        System.err.println("结果：" + rainNum / count);
        return rainNum / count;


    }

    /**
     * 预警区刷新，多边形查询乡界面
     */
    public static List<Location> getCountryMap(String dmgisIp, String dmgisPort, String serveName, StringBuilder sb) {
        List<Location> locationsList = new ArrayList<>();
        try {
            DmServiceConnector conn = new DmServiceConnector(dmgisIp, dmgisPort);
            String xml = "";
            //属性服务
            DmFeatureMapService dmFeatureMapService = new DmFeatureMapService();
            dmFeatureMapService.setStrLayerName("县界面");
            DmFeatureParam dmFeatureParam = new DmFeatureParam();
            dmFeatureParam.setAttribute(1);
            dmFeatureParam.setFeatureLimit(0);
            dmFeatureMapService.setParam(dmFeatureParam);
            dmFeatureMapService.setType("0");
            DmSql dmSql = new DmSql();
            dmSql.setStrPos(sb.toString());
            dmFeatureMapService.setM_sql(dmSql);
            xml = dmFeatureMapService.getXmlString();
//            System.out.println(xml);
            String res = conn.getServiceXml(serveName, 2, xml);
//            System.out.println(res);
            List<Location> locations = CommonServiceImpl.parseXML(res);
//            for (Location location : locations) {
//                Location location1 = new Location();
//                String code = location.getCode();
//                String cityCode = code.substring(0, 4) + "00";
//                //根据市级code查询市级名称
//                String cityName = zdda01aService.queryCityName(cityCode);
//                location1.setCountry(cityName);
//                location1.setCity(location.getName());
//                locationsList.add(location1);
//            }
            //根据
            return locations;
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("服务连接失败");
            return new ArrayList<>();
        }

    }

    public static List<Location> getCountryMapCountry(String dmgisIp, String dmgisPort, String serveName, StringBuilder sb) {
        try {
            DmServiceConnector conn = new DmServiceConnector(dmgisIp, dmgisPort);
            String xml = "";
            //属性服务
            DmFeatureMapService dmFeatureMapService = new DmFeatureMapService();
            dmFeatureMapService.setStrLayerName("乡界面");
            DmFeatureParam dmFeatureParam = new DmFeatureParam();
            dmFeatureParam.setAttribute(1);
            dmFeatureParam.setFeatureLimit(0);
            dmFeatureMapService.setParam(dmFeatureParam);
            dmFeatureMapService.setType("0");
            DmSql dmSql = new DmSql();
            dmSql.setStrPos(sb.toString());
            dmFeatureMapService.setM_sql(dmSql);
            xml = dmFeatureMapService.getXmlString();
//            System.out.println(xml);
            String res = conn.getServiceXml(serveName, 2, xml);
//            System.out.println(res);
            List<Location> locations = CommonServiceImpl.parseXML(res);
            return locations;
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("服务连接失败");
            return new ArrayList<>();
        }

    }

    /**
     * 属性查询服务
     * @param dmgisIp
     * @param dmgisPort
     * @param serveName
     * @param sb
     * @param layerName "村庄"
     * @return
     */
    public static List<Location> getMapAnalysis(String dmgisIp, String dmgisPort, String serveName, StringBuilder sb, String layerName) {
        try {
            DmServiceConnector conn = new DmServiceConnector(dmgisIp, dmgisPort);
            String xml = "";
            //属性服务
            DmFeatureMapService dmFeatureMapService = new DmFeatureMapService();
            dmFeatureMapService.setStrLayerName(layerName);
            DmFeatureParam dmFeatureParam = new DmFeatureParam();
            dmFeatureParam.setAttribute(1);
            dmFeatureParam.setFeatureLimit(0);
            dmFeatureMapService.setParam(dmFeatureParam);
            dmFeatureMapService.setType("0");
            DmSql dmSql = new DmSql();
            dmSql.setStrPos(sb.toString());
            dmFeatureMapService.setM_sql(dmSql);
            xml = dmFeatureMapService.getXmlString();
            String res = conn.getServiceXml(serveName, 2, xml);
            List<Location> locations = CommonServiceImpl.parseXML(res);
            return locations;
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("服务连接失败");
            return new ArrayList<>();
        }

    }

    public static List<Location> getCountryMapCounty(String dmgisIp, String dmgisPort, String serveName, double[][] pos) {
        try {
            StringBuilder sb = new StringBuilder();
            for (double[] po : pos) {
                sb.append(po[0]).append(" ").append(po[1]).append(";");
            }
            sb.deleteCharAt(sb.length() - 1);
            DmServiceConnector conn = new DmServiceConnector(dmgisIp, dmgisPort);
            String xml = "";
            //属性服务
            DmFeatureMapService dmFeatureMapService = new DmFeatureMapService();
            dmFeatureMapService.setStrLayerName("村庄");
            DmFeatureParam dmFeatureParam = new DmFeatureParam();
            dmFeatureParam.setAttribute(1);
            dmFeatureParam.setFeatureLimit(0);
            dmFeatureMapService.setParam(dmFeatureParam);
            dmFeatureMapService.setType("0");
            DmSql dmSql = new DmSql();
            dmSql.setStrPos(sb.toString());
            dmFeatureMapService.setM_sql(dmSql);
            xml = dmFeatureMapService.getXmlString();
//            System.out.println(xml);
            String res = conn.getServiceXml(serveName, 2, xml);
//            System.out.println(res);
            List<Location> locations = CommonServiceImpl.parseXML(res);
            return locations;
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("服务连接失败");
            return new ArrayList<>();
        }

    }

    /**
     * 解析多边形查询结果
     *
     * @return
     */
    public static Map<Integer, List<ColorAndNameDto>> getColorAndNameMap(String type, String color, List<DmObj> map) {
        Map<Integer, List<ColorAndNameDto>> colorAndNameMap = new HashMap<>();
        for (DmObj obj : map) {
            List<DmRcoVal> rec = obj.getRec();
            for (DmRcoVal dmRcoVal : rec) {
                String fldName = dmRcoVal.getFldName();
                if (fldName.equals("NAME")) {
                    ColorAndNameDto colorAndNameDto = new ColorAndNameDto();
                    colorAndNameDto.setCounty("义乌");
                    colorAndNameDto.setCountry(dmRcoVal.getFldVal());
                    colorAndNameDto.setType(Integer.parseInt(type));
                    colorAndNameDto.setColor(color);
                    List<ColorAndNameDto> colorAndNameDtoList = null;
                    if (colorAndNameMap.containsKey(Integer.parseInt(type))) {
                        colorAndNameDtoList = colorAndNameMap.get(Integer.parseInt(type));
                    } else {
                        colorAndNameDtoList = new ArrayList<>();
                    }
                    colorAndNameDtoList.add(colorAndNameDto);
                    colorAndNameMap.put(Integer.parseInt(type), colorAndNameDtoList);
                    break;
                }
            }
        }
        return colorAndNameMap;
    }

}

